/* 
 * File:   LevelEditor.cpp
 * Copyright (C) 2008, 2009
 *		Sergio Padrino Recio (PadrinatoR)
 *
 * Created on 19 de septiembre de 2008, 18:41
 *
 * This file is part of BombProject.
 * 
 * BombProject is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
   
 * BombProject is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with BombProject.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "AnimatedSprite.h"


#include "ConfigurationFile.h"


#include "Sprite.h"

#include <SDL/SDL_video.h>
#include <SDL/SDL_gfxPrimitives.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_mouse.h>
#include <SDL/SDL_keysym.h>
#include <SDL/SDL_events.h>

#include "LevelEditor.h"
#include "ResourceManager.h"
#include "Files.h"

#include <vector>
#include <string>

using namespace std;

/**
 * Constructor.
 */
LevelEditor::LevelEditor(){
	mGameOffsetX = 48;
	mGameOffsetY = 86;
	
	mTileWidth = 32;
	mTileHeight = 32;
	
	mGameWidth = mTileWidth * 17;
	mGameHeight = mTileHeight * 11;
	
/*	mLevelsPath = "/home/sergio/Levels/";
	mSkinsPath = "/home/sergio/Skins/Level/";*/
	mLevelsPath = "./Levels/";
	mSkinsPath = "./Skins/Level/";
	mSkinName = "Default";

	string nameList[NUM_TILES] = { "Player Start", "Always Empty", "Empty/Brick with Item", "Brick with Item", "Brick without Item",
		"Conveyor Belt L-R", "Conveyor Belt U-D", "Conveyor Belt U-L", "Conveyor Belt U-R", "Conveyor Belt D-L", "Conveyor Belt D-R",
		"Indestructible Block", "Arrow Up", "Arrow Down", "Arrow Left", "Arrow Right", "Seesaw", "Tunnel",
		"Bouncing Statue", "Trapdoor", "Hole", "Random Item" };
	
	string seqList[NUM_TILES] = { "", "", "", "brick.seq", "brick.seq",
		"belt_l_r.seq", "belt_u_d.seq", "belt_u_l.seq", "belt_u_r.seq", "belt_d_l.seq", "belt_d_r.seq",
		"indestructible_block.seq", "arrow_up.seq", "arrow_down.seq", "arrow_left.seq", "arrow_right.seq", "seesaw.seq", "tunnel.seq",
		"bouncing_statue.seq", "trapdoor.seq", "hole.seq", "bomb_up.seq" };
	
	for(int i = 0; i < NUM_TILES; i++){
		mTileNameList[i] = nameList[i];
		mTileSeqList[i] = seqList[i];
	}
	
	mMapName = "";

	for(int j = 0; j < 11; j++)
		for(int i = 0; i < 17; i++){
			mLevelTiles[i][j] = TILE_ALWAYS_EMPTY;
			mLevelSurfaces[i][j] = NULL;
		}
	
	mMapModified = false;
}

/**
 * Destructor.
 */
LevelEditor::~LevelEditor(){
	
}

/**
 * Runs the editor.
 */
void LevelEditor::run(){
	init();

	for(;;){
		if(!selectLevel()) break;
		
		if(!tileEditor()) break;
	}
	
	destroy();
	
	exit(0);
}

/**
 * Inits the editor.
 */
void LevelEditor::init(){
    if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
        fprintf(stderr, "SDL couldn't be initialised: %s\n", SDL_GetError());
        exit(1);
    }
	
    atexit(SDL_Quit); // Al salir, cierra SDL

    mScreenSurface = SDL_SetVideoMode(1024, 480, 32, SDL_ANYFORMAT | SDL_DOUBLEBUF);// | SDL_FULLSCREEN);

    if (mScreenSurface == NULL) {
        fprintf(stderr, "Error: main surface couldn't be created: %s\n", SDL_GetError());
        exit(1);
    }
	
    // Personalizamos el título de la ventana
    SDL_WM_SetCaption("Bomberman Project - LEVEL EDITOR - By Format C 2008", NULL);

	//FPS manager initialization
	SDL_initFramerate(&mFramerateManager);
	SDL_setFramerate(&mFramerateManager, 30);
}

/**
 * Shows the level selection window.
 * @return true if a level (existing or new) was selected.
 */
bool LevelEditor::selectLevel(){
	SDL_Event event;
	vector<string> levelsList = getFileList(mLevelsPath, "lev");
	
	//Test levels list
	/*levelsList.push_back("nivel1.lev");
	levelsList.push_back("nivel2.lev");
	levelsList.push_back("nivel_extra.lev");
	levelsList.push_back("nivel_bomberman.lev");
	levelsList.push_back("nivel1.lev");
	levelsList.push_back("nivel2.lev");
	levelsList.push_back("nivel_extra.lev");
	levelsList.push_back("nivel_bomberman.lev");
	levelsList.push_back("nivel1.lev");
	levelsList.push_back("nivel2.lev");
	levelsList.push_back("nivel_extra.lev");
	levelsList.push_back("nivel_bomberman.lev");
	levelsList.push_back("nivel1.lev");
	levelsList.push_back("nivel2.lev");
	levelsList.push_back("nivel_extra.lev");
	levelsList.push_back("nivel_bomberman.lev");
	levelsList.push_back("nivel1.lev");
	levelsList.push_back("nivel2.lev");
	levelsList.push_back("nivel_extra.lev");
	levelsList.push_back("nivel_bomberman.lev");
	levelsList.push_back("nivel1.lev");
	levelsList.push_back("nivel2.lev");
	levelsList.push_back("nivel_extra.lev");
	levelsList.push_back("nivel_bomberman.lev");
	levelsList.push_back("nivel1.lev");
	levelsList.push_back("nivel2.lev");
	levelsList.push_back("nivel_extra.lev");
	levelsList.push_back("nivel_bomberman.lev");
	levelsList.push_back("nivel1.lev");
	levelsList.push_back("nivel2.lev");
	levelsList.push_back("nivel_extra.lev");
	levelsList.push_back("nivel_bomberman.lev");
	levelsList.push_back("nivel1.lev");
	levelsList.push_back("nivel2.lev");
	levelsList.push_back("nivel_extra.lev");
	levelsList.push_back("nivel_bomberman.lev");
	levelsList.push_back("nivel1.lev");
	levelsList.push_back("nivel2.lev");
	levelsList.push_back("nivel_extra.lev");
	levelsList.push_back("nivel_bomberman.lev");
	levelsList.push_back("nivel1.lev");
	levelsList.push_back("nivel2.lev");
	levelsList.push_back("nivel_extra.lev");
	levelsList.push_back("nivel_bomberman.lev");*/
	
	int width = 600, height = 400, border = 5;
	int list_offset = 0, list_selected = 0;
	
	for(;;){
		while (SDL_PollEvent(&event)) {

			//Clears the background
			boxRGBA(mScreenSurface, 0, 0, 1024, 480, 0x33, 0x33, 0x33, 0xFF);
			
			//The Window itself
			boxRGBA(mScreenSurface, 512 - width/2 - border, 240 - height/2 - border, 512 + width/2 + border, 240 + height/2 + border, 0x80, 0x80, 0x80, 0xFF);
			boxRGBA(mScreenSurface, 512 - width/2, 240 - height/2, 512 + width/2, 240 + height/2, 0xC0, 0xC0, 0xC0, 0xFF);

			//Levels list
			for(int i = 0; i < 30; i+=2){
				if(list_offset + i == list_selected)
					boxRGBA(mScreenSurface, 512 - width/2 + border*4, 240 - height/2 + border*4 + i*12, 512 + width/4, 240 - height/2 + border*4 + i*12 + 12, 0xC2, 0xC7, 0xFF, 0xFF);
				else
					boxRGBA(mScreenSurface, 512 - width/2 + border*4, 240 - height/2 + border*4 + i*12, 512 + width/4, 240 - height/2 + border*4 + i*12 + 12, 0xC3, 0xC3, 0xC3, 0xFF);

				if(i < levelsList.size()) stringRGBA(mScreenSurface, 512 - width/2 + border*5, 240 - height/2 + border*4 + i*12 + 2, levelsList[list_offset + i].c_str(), 0, 0, 0, 255);

				if(list_offset + i + 1 == list_selected)
					boxRGBA(mScreenSurface, 512 - width/2 + border*4, 240 - height/2 + border*4 + i*12 + 12, 512 + width/4, 240 - height/2 + border*4 + i*12 + 24, 0xC2, 0xC7, 0xFF, 0xFF);
				else
					boxRGBA(mScreenSurface, 512 - width/2 + border*4, 240 - height/2 + border*4 + i*12 + 12, 512 + width/4, 240 - height/2 + border*4 + i*12 + 24, 0xDC, 0xDC, 0xDC, 0xFF);

				if(i + 1 < levelsList.size()) stringRGBA(mScreenSurface, 512 - width/2 + border*5, 240 - height/2 + border*4 + i*12 + 14, levelsList[list_offset + i + 1].c_str(), 0, 0, 0, 255);
			}
			rectangleRGBA(mScreenSurface, 512 - width/2 + border*4, 240 - height/2 + border*4, 512 + width/4, 240 + height/2 - border*4, 30, 30, 30, 0xFF);

			//"Scrollbar" Up
			boxRGBA(mScreenSurface, 512 + width/4, 240 - height/2 + border*4, 512 + width/4 + 30, 240, 0x80, 0x80, 0x80, 0xFF);
			rectangleRGBA(mScreenSurface, 512 + width/4, 240 - height/2 + border*4, 512 + width/4 + 30, 240, 30, 30, 30, 0xFF);
			filledTrigonRGBA(mScreenSurface, 512 + width/4 + 5, 240 - border*4, 512 + width/4 + 25, 240 - border*4, 512 + width/4 + 15, 240 - height/2 + border*8, 0x33, 0x33, 0x33, 0xFF);

			//"Scrollbar" Down
			boxRGBA(mScreenSurface, 512 + width/4, 240, 512 + width/4 + 30, 240 + height/2 - border*4, 0x80, 0x80, 0x80, 0xFF);
			rectangleRGBA(mScreenSurface, 512 + width/4, 240, 512 + width/4 + 30, 240 + height/2 - border*4, 30, 30, 30, 0xFF);
			filledTrigonRGBA(mScreenSurface, 512 + width/4 + 5, 240 + border*4, 512 + width/4 + 25, 240 + border*4, 512 + width/4 + 15, 240 + height/2 - border*8, 0x33, 0x33, 0x33, 0xFF);

			//LOAD BUTTON
			boxRGBA(mScreenSurface, 512 + width/2 - border*4 - 80, 240 - height/2 + border*4, 512 + width/2 - border*4, 240 - height/2 + border*4 + 40, 0x80, 0x80, 0x80, 0xFF);
			rectangleRGBA(mScreenSurface, 512 + width/2 - border*4 - 80, 240 - height/2 + border*4, 512 + width/2 - border*4, 240 - height/2 + border*4 + 40, 30, 30, 30, 0xFF);
			stringRGBA(mScreenSurface, 512 + width/2 - border*4 - 80 + 23, 240 - height/2 + border*4 + 17, "LOAD", 0, 0, 0, 255);

			//NEW BUTTON
			boxRGBA(mScreenSurface, 512 + width/2 - border*4 - 80, 240 + height/2 - border*4 - 40, 512 + width/2 - border*4, 240 + height/2 - border*4, 0x80, 0x80, 0x80, 0xFF);
			rectangleRGBA(mScreenSurface, 512 + width/2 - border*4 - 80, 240 + height/2 - border*4 - 40, 512 + width/2 - border*4, 240 + height/2 - border*4, 30, 30, 30, 0xFF);
			stringRGBA(mScreenSurface, 512 + width/2 - border*4 - 80 + 25, 240 + height/2 - border*4 - 40 + 17, "NEW", 0, 0, 0, 255);

			SDL_Flip(mScreenSurface);

			if (event.type == SDL_QUIT){ // Si es de salida
				return false;
			}else if(event.type == SDL_KEYDOWN){
				switch(event.key.keysym.sym){
					case SDLK_ESCAPE:
						return false;
				}
			}else if(event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT){
				//Click on the list
				if(mouseInRectangle(event.button.x, event.button.y,
						512 - width/2 + border*4, 240 - height/2 + border*4, 512 + width/4, 240 + height/2 - border*4)){

					int item_selected = (event.button.y - (240 - height/2 + border*4)) / 12;
					
					if(item_selected + list_offset < levelsList.size())
						list_selected = item_selected + list_offset;
				}else if(mouseInRectangle(event.button.x, event.button.y,	//Click on the Up scrollbar
						512 + width/4, 240 - height/2 + border*4, 512 + width/4 + 30, 240)){
					
					if(list_offset > 0) list_offset--;					
				}else if(mouseInRectangle(event.button.x, event.button.y,	//Click on the Down scrollbar
						512 + width/4, 240, 512 + width/4 + 30, 240 + height/2 - border*4)){
					
					if(levelsList.size() - list_offset > 30) list_offset++;
				}else if(mouseInRectangle(event.button.x, event.button.y,	//Click on the LOAD button
						512 + width/2 - border*4 - 80, 240 - height/2 + border*4, 512 + width/2 - border*4, 240 - height/2 + border*4 + 40)){
					
					if(levelsList.size() > 0){
						loadLevel(levelsList[list_selected]);
						return true;
					}
				}else if(mouseInRectangle(event.button.x, event.button.y,	//Click on the NEW button
						512 + width/2 - border*4 - 80, 240 + height/2 - border*4 - 40, 512 + width/2 - border*4, 240 + height/2 - border*4)){

					string filename = InputString("Enter a name for the new level") + ".lev";
					
					SDL_RWops* map = SDL_RWFromFile((mLevelsPath + filename).c_str(), "r");
					if(map != NULL){
						SDL_RWclose(map);
						
						break;
					}
					
					for(int i = 0; i < 17; i++)
						for(int j = 0; j < 11; j++)
							removeItem(i, j);
					
					mMapName = filename;
					mMapModified = false;
					return true;
				}
			}
		}
	}
	
	return true;
}

/**
 * Checks if the mouse (or whatever) is in the specified rectangle.
 * @param mx Mouse X
 * @param my Mouse Y
 * @param x1 X coordinate for the top-left corner
 * @param y1 Y coordinate for the top-left corner
 * @param x2 X coordinate for the bottom-right corner
 * @param y2 Y coordinate for the bottom-right corner
 * @return true if the point (mx,my) is contained in the specified rectangle.
 */
bool LevelEditor::mouseInRectangle(int mx, int my, int x1, int y1, int x2, int y2){
	return (mx >= x1) && (mx <= x2) && (my >= y1) && (my <= y2);
}

/**
 * Asks the user to input a string value.
 * @param prompt Prompt to ask the user.
 * @return The string typed by the user.
 */
string LevelEditor::InputString(string prompt){
	SDL_Event event;
	string result = "";
	string shown_text = "";
	
	for(;;){
		while (SDL_PollEvent(&event)) {
			shown_text = prompt + ": " + result + "_";
					
			boxRGBA(mScreenSurface, 0, 0, 1024, 15, 0x33, 0x33, 0x33, 0xFF);
			stringRGBA(mScreenSurface, 0, 0, shown_text.c_str(), 255, 255, 255, 255);
			
			SDL_Flip(mScreenSurface);

			if (event.type == SDL_QUIT){ // Si es de salida
				exit(0);
			}else if(event.type == SDL_KEYDOWN){
				switch(event.key.keysym.sym){
					case SDLK_ESCAPE:
						return "";
					case SDLK_BACKSPACE:
						if(result != "") result = result.substr(0, result.length() - 1);
						break;
					case SDLK_RETURN:
						return result;
					default:
						if((event.key.keysym.sym >= SDLK_a && event.key.keysym.sym <= SDLK_z) ||
								(event.key.keysym.sym >= SDLK_0 && event.key.keysym.sym <= SDLK_9) ||
								event.key.keysym.sym == SDLK_MINUS)
							result += (char) (event.key.keysym.sym);
						break;
				}
			}
		}
	}
	
	return result;
}

/**
 * Tile editor itself.
 * @return true if the user wants to return to the level selection window, false if wants to leave.
 */
bool LevelEditor::tileEditor(){
	bool bRedrawGUI = true;
	SDL_Event event;
	int mouse_x = 0, mouse_y = 0;
	int tile_x = 0, tile_y = 0;
	int list_offset = 0, list_selected = 0;

	AnimatedSprite cursor;
	cursor.setAlpha(180);	

	mBackground = ResourceManager::getInstance()->loadImage(mSkinsPath + mSkinName + "/background.png");

	boxRGBA(mScreenSurface, 0, 0, 640, 480, 0x33, 0x33, 0x33, 0xFF);
	boxRGBA(mScreenSurface, 640, 0, 1024, 480, 0xC0, 0xC0, 0xC0, 0xFF);
	
	for(;;){
		while (SDL_PollEvent(&event)) {
			if (event.type == SDL_QUIT){ 
				return false;
			}else if(event.type == SDL_MOUSEMOTION){	//Mouse motion
				mouse_x = event.button.x;
				mouse_y = event.button.y;
				
				tile_x = (mouse_x - mGameOffsetX) / mTileWidth;
				tile_y = (mouse_y - mGameOffsetY) / mTileHeight;

				cursor.setPosition(tile_x * mTileWidth + mGameOffsetX + mTileWidth/2, tile_y * mTileHeight + mGameOffsetY + mTileHeight);
			}else if(event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT){
				//Click on the grid
				if(mouseInRectangle(event.button.x, event.button.y, mGameOffsetX, mGameOffsetY,
						mGameOffsetX + mGameWidth - 1, mGameOffsetY + mGameHeight - 1)){
					
					putItem(tile_x, tile_y, (LevelTileType) list_selected);
				}else if(mouseInRectangle(event.button.x, event.button.y, //Click on the list
						650, 10, 860, 466)){

					int item_selected = (event.button.y - 10) / 12;
					if(item_selected + list_offset < NUM_TILES){
						list_selected = item_selected + list_offset;
						bRedrawGUI = true;
						
						//Select the new cursor
						cursor.removeAllAnimations();
						if(mTileSeqList[list_selected] != ""){
							cursor.addAnimation("cursor", mSkinsPath + mSkinName + "/" + mTileSeqList[list_selected]);
							cursor.playAnimation();
						}
					}
					
				}else if(mouseInRectangle(event.button.x, event.button.y,	//Click on the Up scrollbar
						860, 10, 860 + 30, 240)){
					
					if(list_offset > 0){
						list_offset--;
						bRedrawGUI = true;
					}					
				}else if(mouseInRectangle(event.button.x, event.button.y,	//Click on the Down scrollbar
						860, 240, 860 + 30, 466)){
					
					if(NUM_TILES - list_offset > 30){
						list_offset++;
						bRedrawGUI = true;
					}
				}else if(mouseInRectangle(event.button.x, event.button.y,	//Click on the SAVE button
						905, 10, 1004, 30)){
					
					saveLevel();
				}else if(mouseInRectangle(event.button.x, event.button.y,	//Click on the RETURN button
						905, 50, 1004, 70)){
					
					return true;
				}else if(mouseInRectangle(event.button.x, event.button.y,	//Click on the QUIT button
						905, 446, 1004, 466)){
					
					return false;
				}
			}else if(event.type == SDL_KEYDOWN){
				switch(event.key.keysym.sym){
					case SDLK_ESCAPE:
						return false;
				}
			}
		}
		
		//Draws the background
		SDL_BlitSurface(mBackground, NULL, mScreenSurface, NULL);

		//Drawing the grid
		for(int i = 0; i < 18; i++){
			lineRGBA(mScreenSurface, i*mTileWidth + mGameOffsetX, mGameOffsetY, i*mTileHeight + mGameOffsetX, mGameOffsetY + mGameHeight, 255, 255, 0, 255);

			if(i < 12)
				lineRGBA(mScreenSurface, mGameOffsetX, i*mTileWidth + mGameOffsetY, mGameOffsetX + mGameWidth, i*mTileHeight + mGameOffsetY, 255, 255, 0, 255);
		}

		//Draws tiles
		for(int j = 0; j < 11; j++){
			for(int i = 0; i < 17; i++){
				if(mLevelSurfaces[i][j] != NULL){
					mLevelSurfaces[i][j]->updateAnimation();
					mLevelSurfaces[i][j]->draw(mScreenSurface);
				}

				//Prints additional data over the tiles
				switch(mLevelTiles[i][j]){
					case TILE_PLAYER_START:
						stringRGBA(mScreenSurface, i * mTileWidth + mGameOffsetX + 12, j *mTileHeight + mGameOffsetY + 13, "PS", 0, 0, 0, 255);
						stringRGBA(mScreenSurface, i * mTileWidth + mGameOffsetX + 10, j *mTileHeight + mGameOffsetY + 12, "PS", 255, 0, 0, 255);
						break;
					case TILE_EMPTY_OR_BRICK:
					case TILE_BRICK_ITEM:
						stringRGBA(mScreenSurface, i * mTileWidth + mGameOffsetX + 13, j *mTileHeight + mGameOffsetY + 13, "?", 0, 0, 0, 255);
						stringRGBA(mScreenSurface, i * mTileWidth + mGameOffsetX + 11, j *mTileHeight + mGameOffsetY + 12, "?", 255, 0, 0, 255);
						break;
					case TILE_BRICK_NO_ITEM:
						stringRGBA(mScreenSurface, i * mTileWidth + mGameOffsetX + 12, j *mTileHeight + mGameOffsetY + 13, "NO", 0, 0, 0, 255);
						stringRGBA(mScreenSurface, i * mTileWidth + mGameOffsetX + 10, j *mTileHeight + mGameOffsetY + 12, "NO", 255, 0, 0, 255);
						break;
					default:
						break;
				}
			}
		}

		//Draws the cursor
		cursor.setVisible(false);
		if(mouseInRectangle(mouse_x, mouse_y, mGameOffsetX, mGameOffsetY, mGameOffsetX + mGameWidth - 1, mGameOffsetY + mGameHeight - 1)){
			//Switch for special mouse cursors
			switch((LevelTileType) list_selected){
				case TILE_PLAYER_START:
					boxRGBA(mScreenSurface, mGameOffsetX + tile_x * mTileWidth, mGameOffsetY + tile_y * mTileHeight,
							mGameOffsetX + tile_x * mTileWidth + mTileWidth, mGameOffsetY + tile_y * mTileHeight + mTileHeight, 0, 0xFF, 0, 0x10);
					stringRGBA(mScreenSurface, tile_x * mTileWidth + mGameOffsetX + 12, tile_y *32 + mGameOffsetY + 13, "PS", 0, 0, 0, 255);
					stringRGBA(mScreenSurface, tile_x * mTileWidth + mGameOffsetX + 10, tile_y *32 + mGameOffsetY + 12, "PS", 255, 0, 0, 255);

					break;
				case TILE_ALWAYS_EMPTY:
					boxRGBA(mScreenSurface, mGameOffsetX + tile_x * mTileWidth, mGameOffsetY + tile_y * 32,
							mGameOffsetX + tile_x * mTileWidth + mTileWidth, mGameOffsetY + tile_y * mTileHeight + mTileHeight, 0, 0xFF, 0, 0x10);

					break;
				case TILE_EMPTY_OR_BRICK:
					boxRGBA(mScreenSurface, mGameOffsetX + tile_x * mTileWidth, mGameOffsetY + tile_y * mTileHeight,
							mGameOffsetX + tile_x * mTileWidth + mTileWidth, mGameOffsetY + tile_y * mTileHeight + mTileHeight, 0, 0xFF, 0, 0x10);
					stringRGBA(mScreenSurface, tile_x * mTileWidth + mGameOffsetX + 13, tile_y *mTileHeight + mGameOffsetY + 13, "?", 0, 0, 0, 255);
					stringRGBA(mScreenSurface, tile_x * mTileWidth + mGameOffsetX + 11, tile_y *mTileHeight + mGameOffsetY + 12, "?", 255, 0, 0, 255);

					break;
				case TILE_BRICK_ITEM:
					cursor.setVisible(true);
					cursor.updateAnimation();
					cursor.draw(mScreenSurface);

					stringRGBA(mScreenSurface, tile_x * mTileWidth + mGameOffsetX + 13, tile_y *mTileHeight + mGameOffsetY + 13, "?", 0, 0, 0, 255);
					stringRGBA(mScreenSurface, tile_x * mTileWidth + mGameOffsetX + 11, tile_y *mTileHeight + mGameOffsetY + 12, "?", 255, 0, 0, 255);

					break;
				case TILE_BRICK_NO_ITEM:
					cursor.setVisible(true);
					cursor.updateAnimation();
					cursor.draw(mScreenSurface);

					stringRGBA(mScreenSurface, tile_x * mTileWidth + mGameOffsetX + 12, tile_y *mTileHeight + mGameOffsetY + 13, "NO", 0, 0, 0, 255);
					stringRGBA(mScreenSurface, tile_x * mTileWidth + mGameOffsetX + 10, tile_y *mTileHeight + mGameOffsetY + 12, "NO", 255, 0, 0, 255);

					break;
				default:
					cursor.setVisible(true);
					cursor.updateAnimation();
					cursor.draw(mScreenSurface);

					break;
			}
		}

		//Redraws the GUI if it's needed
		if(bRedrawGUI){
			//Tiles list
			for(int i = 0; i < 38; i+=2){
				if(list_offset + i == list_selected)
					boxRGBA(mScreenSurface, 650, 10 + i*12, 860, 10 + i*12 + 12, 0xC2, 0xC7, 0xFF, 0xFF);
				else
					boxRGBA(mScreenSurface, 650, 10 + i*12, 860, 10 + i*12 + 12, 0xC3, 0xC3, 0xC3, 0xFF);

				if(i < NUM_TILES) stringRGBA(mScreenSurface, 655, 10 + i*12 + 2, mTileNameList[list_offset + i].c_str(), 0, 0, 0, 255);

				if(list_offset + i + 1 == list_selected)
					boxRGBA(mScreenSurface, 650, 10 + i*12 + 12, 860, 10 + i*12 + 24, 0xC2, 0xC7, 0xFF, 0xFF);
				else
					boxRGBA(mScreenSurface, 650, 10 + i*12 + 12, 860, 10 + i*12 + 24, 0xDC, 0xDC, 0xDC, 0xFF);

				if(i + 1 < NUM_TILES) stringRGBA(mScreenSurface, 655, 10 + i*12 + 14, mTileNameList[list_offset + i + 1].c_str(), 0, 0, 0, 255);
			}
			rectangleRGBA(mScreenSurface, 650, 10, 860, 466, 30, 30, 30, 0xFF);

			//"Scrollbar" Up
			boxRGBA(mScreenSurface, 860, 10, 860 + 30, 240, 0x80, 0x80, 0x80, 0xFF);
			rectangleRGBA(mScreenSurface, 860, 10, 860 + 30, 240, 30, 30, 30, 0xFF);
			filledTrigonRGBA(mScreenSurface, 860 + 5, 240 - 20, 860 + 25, 240 - 20, 860 + 15, 10 + 40, 0x33, 0x33, 0x33, 0xFF);

			//"Scrollbar" Down
			boxRGBA(mScreenSurface, 860, 240, 860 + 30, 466, 0x80, 0x80, 0x80, 0xFF);
			rectangleRGBA(mScreenSurface, 860, 240, 860 + 30, 466, 30, 30, 30, 0xFF);
			filledTrigonRGBA(mScreenSurface, 860 + 5, 240 + 20, 860 + 25, 240 + 20, 860 + 15, 466 - 40, 0x33, 0x33, 0x33, 0xFF);

			//RETURN BUTTON
			boxRGBA(mScreenSurface, 905, 50, 1004, 70, 0x80, 0x80, 0x80, 0xFF);
			rectangleRGBA(mScreenSurface, 905, 50, 1004, 70, 30, 30, 30, 0xFF);
			stringRGBA(mScreenSurface, 930, 56, "RETURN", 0, 0, 0, 255);

			bRedrawGUI = false;
		}

		//SAVE BUTTON
		boxRGBA(mScreenSurface, 905, 10, 1004, 30, 0x80, 0x80, 0x80, 0xFF);
		rectangleRGBA(mScreenSurface, 905, 10, 1004, 30, 30, 30, 30, 0xFF);
		if(mMapModified)
			stringRGBA(mScreenSurface, 940, 16, "SAVE", 255, 0, 0, 255);
		else
			stringRGBA(mScreenSurface, 940, 16, "SAVE", 0, 0, 0, 255);

		//QUIT BUTTON
		boxRGBA(mScreenSurface, 905, 446, 1004, 466, 0x80, 0x80, 0x80, 0xFF);
		rectangleRGBA(mScreenSurface, 905, 446, 1004, 466, 30, 30, 30, 0xFF);
		if(mMapModified)
			stringRGBA(mScreenSurface, 940, 452, "QUIT", 255, 0, 0, 255);
		else
			stringRGBA(mScreenSurface, 940, 452, "QUIT", 0, 0, 0, 255);

		SDL_Flip(mScreenSurface);
	}
	
	return true;
}

/**
 * Puts an item in the editing level. It removes whatever is need to be removed before putting the new item.
 * @param tile_x Tile X
 * @param tile_y Tile Y
 * @param tile_type Item to be put.
 */
void LevelEditor::putItem(int tile_x, int tile_y, LevelTileType tile_type){
	if((int) tile_type >= NUM_TILES) return;
	
	switch(tile_type){
		case TILE_SEESAW:
			if(tile_x < 1 || tile_x > 15) return;	//Limits
			
			removeItem(tile_x - 1, tile_y);
			removeItem(tile_x + 1, tile_y);
			
			mLevelTiles[tile_x-1][tile_y] = TILE_SEESAW_LEFT;
			mLevelTiles[tile_x+1][tile_y] = TILE_SEESAW_RIGHT;

			break;
		case TILE_TUNNEL:
			if(tile_x < 1 || tile_x > 15 || tile_y < 2) return;	//Limits
			
			removeItem(tile_x - 1, tile_y - 2);
			removeItem(tile_x    , tile_y - 2);
			removeItem(tile_x + 1, tile_y - 2);
			removeItem(tile_x - 1, tile_y - 1);
			removeItem(tile_x    , tile_y - 1);
			removeItem(tile_x + 1, tile_y - 1);
			removeItem(tile_x - 1, tile_y);
			removeItem(tile_x + 1, tile_y);

			mLevelTiles[tile_x - 1][tile_y - 2] = TILE_TUNNEL_AUX11;
			mLevelTiles[tile_x    ][tile_y - 2] = TILE_TUNNEL_AUX12;
			mLevelTiles[tile_x + 1][tile_y - 2] = TILE_TUNNEL_AUX13;
			mLevelTiles[tile_x - 1][tile_y - 1] = TILE_TUNNEL_AUX21;
			mLevelTiles[tile_x    ][tile_y - 1] = TILE_TUNNEL_AUX22;
			mLevelTiles[tile_x + 1][tile_y - 1] = TILE_TUNNEL_AUX23;
			mLevelTiles[tile_x - 1][tile_y] = TILE_TUNNEL_AUX31;
			mLevelTiles[tile_x + 1][tile_y] = TILE_TUNNEL_AUX33;

			break;
		default:
			break;
	}

	removeItem(tile_x, tile_y);
	mLevelTiles[tile_x][tile_y] = tile_type;
	if(mTileSeqList[(int) tile_type] != ""){
		mLevelSurfaces[tile_x][tile_y] = new AnimatedSprite();
		mLevelSurfaces[tile_x][tile_y]->addAnimation("item", mSkinsPath + mSkinName + "/" + mTileSeqList[(int) tile_type]);
		mLevelSurfaces[tile_x][tile_y]->playAnimation();
		mLevelSurfaces[tile_x][tile_y]->setPosition(tile_x * mTileWidth + mGameOffsetX + mTileWidth / 2, tile_y * mTileHeight + mTileHeight + mGameOffsetY);
	}
	
	mMapModified = true;
}

/**
 * Removes an item from the editing level.
 * @param tile_x Tile X
 * @param tile_y Tile Y
 */
void LevelEditor::removeItem(int tile_x, int tile_y){
	switch((LevelTileType) mLevelTiles[tile_x][tile_y]){
		case TILE_ALWAYS_EMPTY:
			return;
		case TILE_SEESAW_LEFT:
			removeItem(tile_x + 1, tile_y);

			return;
		case TILE_SEESAW:
			mLevelTiles[tile_x-1][tile_y] = TILE_ALWAYS_EMPTY;
			mLevelTiles[tile_x+1][tile_y] = TILE_ALWAYS_EMPTY;

			break;
		case TILE_SEESAW_RIGHT:
			removeItem(tile_x - 1, tile_y);

			return;
		case TILE_TUNNEL:
			mLevelTiles[tile_x - 1][tile_y - 2] = TILE_ALWAYS_EMPTY;
			mLevelTiles[tile_x    ][tile_y - 2] = TILE_ALWAYS_EMPTY;
			mLevelTiles[tile_x + 1][tile_y - 2] = TILE_ALWAYS_EMPTY;
			mLevelTiles[tile_x - 1][tile_y - 1] = TILE_ALWAYS_EMPTY;
			mLevelTiles[tile_x    ][tile_y - 1] = TILE_ALWAYS_EMPTY;
			mLevelTiles[tile_x + 1][tile_y - 1] = TILE_ALWAYS_EMPTY;
			mLevelTiles[tile_x - 1][tile_y] = TILE_ALWAYS_EMPTY;
			mLevelTiles[tile_x + 1][tile_y] = TILE_ALWAYS_EMPTY;

			break;
		case TILE_TUNNEL_AUX11: removeItem(tile_x+1,	tile_y+2); return;
		case TILE_TUNNEL_AUX12: removeItem(tile_x,		tile_y+2); return;
		case TILE_TUNNEL_AUX13: removeItem(tile_x-1,	tile_y+2); return;
		case TILE_TUNNEL_AUX21: removeItem(tile_x+1,	tile_y+1); return;
		case TILE_TUNNEL_AUX22: removeItem(tile_x,		tile_y+1); return;
		case TILE_TUNNEL_AUX23: removeItem(tile_x-1,	tile_y+1); return;
		case TILE_TUNNEL_AUX31: removeItem(tile_x+1,	tile_y); return;
		case TILE_TUNNEL_AUX33: removeItem(tile_x-1,	tile_y); return;

		default:
			break;
	}
	
	mLevelTiles[tile_x][tile_y] = TILE_ALWAYS_EMPTY;
	
	if(mLevelSurfaces[tile_x][tile_y] != NULL){
		delete mLevelSurfaces[tile_x][tile_y];
		mLevelSurfaces[tile_x][tile_y] = NULL;
	}
}

/**
 * Saves the current level.
 */
void LevelEditor::saveLevel(){
	string output = "";
	char aux_number[5] = "";
	SDL_RWops* map = SDL_RWFromFile((mLevelsPath + mMapName).c_str(), "w");
	
	if(map == NULL){
		fprintf(stderr, "LevelEditor::saveMap - Couldn't open %s for saving\n", (mLevelsPath + mMapName).c_str());
		return;
	}
	
	for(int j = 0; j < 11; j++){
		sprintf(aux_number, "%d", j+1);
		output += "row" + string(aux_number) + "=";
		
		for(int i = 0; i < 17; i++){
			sprintf(aux_number, "%d", (int) mLevelTiles[i][j]);
			output += aux_number;
			if(i < 16) output += ",";
		}
		
		output += "\n";
	}
	
	SDL_RWwrite(map, output.c_str(), 1, output.length());
	
	SDL_RWclose(map);
	
	mMapModified = false;
}

/**
 * Loads the specified level.
 * @param map_name Level filename.
 */
void LevelEditor::loadLevel(string map_name){
	ConfigurationFile map_file;
	if(!map_file.loadFile(mLevelsPath + map_name)){
		fprintf(stderr, "LevelEditor::loadMap - Map '%s' couldn't be loaded\n", (mLevelsPath + map_name).c_str());
		return;
	}
	
	char aux_number[5] = "";
	for(int j = 0; j < 11; j++){
		sprintf(aux_number, "%d", j+1);
		
		vector<int> row_tiles = map_file.getIntegerList("row" + string(aux_number));
		
		if(row_tiles.size() != 17){
			fprintf(stderr, "LevelEditor::loadMap - Bad level format, it has %d tiles at row %d\n", j, row_tiles.size());
			return;
		}
		
		for(int i = 0; i < 17; i++){
			putItem(i, j, (LevelTileType) row_tiles[i]);
		}
	}
	
	mMapName = map_name;
	mMapModified = false;
}

/**
 * Destroys whatever is needed to be destroyed (within the level editor).
 */
void LevelEditor::destroy(){
	
}
